package com.yuexi.infrastructure.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuexi.domain.exception.ExceptionEnum;
import com.yuexi.domain.repository.SysCodeRepository;
import com.yuexi.domain.syscode.bo.SysCodeQueryBO;
import com.yuexi.domain.syscode.bo.SysCodeResultBO;
import com.yuexi.domain.util.RedisUtil;
import com.yuexi.infrastructure.converter.Converter;
import com.yuexi.infrastructure.db.entity.TSysCode;
import com.yuexi.infrastructure.db.mapper.SysCodeMapper;
import com.zenx.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.utils.StringUtils;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jie
 * @date 2021/12/13 -20:00
 */
@Slf4j
@Repository
public class SysCodeRepositoryImpl extends ServiceImpl<SysCodeMapper, TSysCode> implements SysCodeRepository {

    @Resource
    private RedisUtil redisUtil;

    /**
     * 存储到缓存
     */
    public List<SysCodeResultBO> setCache(String key) {
        SysCodeQueryBO sysCodeQueryBO = new SysCodeQueryBO();
        sysCodeQueryBO.setCode(key);
        List<SysCodeResultBO> sysCodeResultBOList = this.query(sysCodeQueryBO);
        if (CollectionUtils.isEmpty(sysCodeResultBOList)) {
            return null;
        }

        redisUtil.set(key, sysCodeResultBOList);
        return sysCodeResultBOList;
    }

    /**
     * 从缓存获取
     */
    public List<SysCodeResultBO> getCache(Set<String> codeIds) {
        List<SysCodeResultBO> resultList = new ArrayList<>();
        for (String codeId : codeIds) {
            List<SysCodeResultBO> sysCodeResultBOS = redisUtil.parseArray(codeId, SysCodeResultBO.class);
            // 缓存没有数据，从数据库获取并存储
            if (CollectionUtils.isEmpty(sysCodeResultBOS)) {
                sysCodeResultBOS = setCache(codeId);
            }

            if (!CollectionUtils.isEmpty(sysCodeResultBOS)) {
                resultList.addAll(sysCodeResultBOS);
            }
        }

        return resultList;
    }

    @Override
    public List<SysCodeResultBO> query(SysCodeQueryBO sysCodeQueryBO) {
        LambdaQueryWrapper<TSysCode> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(sysCodeQueryBO.getCode())) {
            queryWrapper.eq(TSysCode::getCode, sysCodeQueryBO.getCode());
        }

        if (StringUtils.isNotEmpty(sysCodeQueryBO.getSubCode())) {
            queryWrapper.eq(TSysCode::getSubCode, sysCodeQueryBO.getSubCode());
        }

        queryWrapper.orderByAsc(TSysCode::getDisplayOrder);
        List<TSysCode> sysCodeList = this.list(queryWrapper);
        return Converter.INSTANCE.toSysCodeResultBOList(sysCodeList);
    }

    @Override
    public SysCodeResultBO getOne(SysCodeQueryBO sysCodeQueryBO) {
        String code = Objects.requireNonNull(sysCodeQueryBO.getCode());
        String subCode = Objects.requireNonNull(sysCodeQueryBO.getSubCode());
        Set<String> codeIds = new HashSet<>();
        codeIds.add(code);
        List<SysCodeResultBO> sysCodeResultBOList = getCache(codeIds);
        if (CollectionUtils.isEmpty(sysCodeResultBOList)) {
            log.error("字典: {}, 未维护", code);
            throw new BusinessException(ExceptionEnum.CODE_NOT_EXIST_EXCEPTION);
        }

        List<SysCodeResultBO> codeList = sysCodeResultBOList.stream()
                .filter(sysCodeResultBO -> sysCodeResultBO.getSubCode().equals(subCode))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(codeList)) {
            log.error("字典不存在, code: {} subCode: {}", code, subCode);
            throw new BusinessException(ExceptionEnum.CODE_NOT_EXIST_EXCEPTION);
        }

        return codeList.get(0);
    }

    @Override
    public List<SysCodeResultBO> list(String code) {
        Set<String> codeIds = new HashSet<>();
        codeIds.add(code);
        return batchQuery(codeIds);
    }

    @Override
    public List<SysCodeResultBO> batchQuery(Set<String> codeIds) {
        return getCache(codeIds);
    }
}
